#include<graphics.h>
#include<ctime>
#include<cstdlib>
#include<vector>
using namespace std;

//初始化游戏背景的函数 
void init_game(){
	//设置黑色画布
	setfillcolor(BLACK);
	bar(0,0,16*32,16*32);
	
	//画横纵线,一共画15条 
	for(int i=1;i<=15;i++){
		setcolor(BLUE);
		line(0,i*32,16*32,i*32);
		line(i*32,0,i*32,16*32);
	} 
	
	return;
}


//一个包含游戏全局信息的类
class Game_infor{
	public:
		int map[17][17];
		//包含每个格子的信息,0到9分别表示:
		//空、上下左右的蛇头、蛇身、墙体、加速剂、减速剂、食物
		int speed=1;
		//当前游戏的速度
    
	public:
	    void init_map(){
	    	//初始化map，将其置空 
	    	for(int i=0;i<17;i++){
	    		for(int j=0;j<17;j++){
	    			map[i][j]=0;
				}
			}
			return;
		}
		
		Game_infor(){
			init_map();
			return;
		}
		
		void print_map(){
			//先画好背景
			init_game();
			
			//再画地图
			for(int i=1;i<=16;i++){
				for(int j=1;j<=16;j++){
					
					if(map[i][j]==0){
						continue;//空不需要打印 
					}
					
					PIMAGE img=newimage();
					switch(map[i][j]){
						case 1:getimage(img,"./图片资源/snakeHeadUp.png");break;
						case 2:getimage(img,"./图片资源/snakeHeadRight.png");break;
						case 3:getimage(img,"./图片资源/snakeHeadDown.png");break;
						case 4:getimage(img,"./图片资源/snakeHeadLeft.png");break;
						case 5:getimage(img,"./图片资源/snakeTail.png");break;
						case 6:getimage(img,"./图片资源/wall.png");break;
						case 7:getimage(img,"./图片资源/speedUp.png");break;
						case 8:getimage(img,"./图片资源/speedDown.png");break;
						case 9:getimage(img,"./图片资源/heart.png");break;
						case 10:getimage(img,"./图片资源/ciallo.png");break;
					}
					
					putimage((j-1)*32,(i-1)*32,32,32,img,0,0,getwidth(img),getheight(img));
					delimage(img);
				}
			}
			
			return; 
		}
		
		//随机生成场景的函数 
		void generate_scene(){
			srand(time(NULL));
			//先看看要不要生成
			if(rand()%2!=0){
				//20%的概率
				return; 
			} 
			
			//生成一个7到12的随机数以决定生成什么场景（10到12为墙） 
			int element=rand()%6+7;
			//生成的位置 
			int x=rand()%16+1;
			int y=rand()%16+1;
			
			if(element<10){
				//生成除墙体外的特殊环境元素
				
				//食物太少了，要加点食物
				//二分之一的概率强制变成食物 
				if(rand()%2==1){
					element=9;
				} 
				
				//十分之一的概率变成芳乃
				if(rand()%10==0){
					element=10;
				} 
				
				//对位置合法性的判断
				if(map[x][y]==0){
					map[x][y]=element;//放一个element进去 
				} 
			}else{
				//要生成墙体
				//先看看生成哪个方向的墙体;
				int direction=rand()%4+1;
				
				//再看看要生成多少个？
				int num=rand()%5+1;//最多生成5个
				
				//开始生成
				for(int i=0;i<num;i++){
					if(x>=1&&x<=16&&y>=1&&y<=16&&map[x][y]<=5){
						//只要不是蛇蛇和越界都可以生成，
						map[x][y]=6;
					}
					
					switch(direction){
						case 1:x--;break;
						case 2:y++;break;
						case 3:x++;break;
						case 4:y--;break;
					}
				} 
				 
			}
			
			return;
		}
};


//一个关于蛇信息的类
//
class Body{
    public:
	    int x=-1,y=-1;
	    
	public:
		Body(int x,int y):x(x),y(y){}
};

class Snake{
    public:
	    vector<Body> body;
		int direction=1;//表示脑袋移动的方向：1到4，分别表示上右下左 
	
	public:
	    Snake(int x,int y,int d,Game_infor& game){
	    	body.push_back(Body(x,y));
	    	direction=d;
	    	
	    	//标记蛇头 
	    	game.map[x][y]=direction;
	    	
	    	return;
		}
		
		//增加身长 
		void add_body(){
			body.push_back(Body(-1,-1));
			
			return;
		}
		
		//移动
		void move(Game_infor& game){
			//先移动身体部分 
		    for(int i=body.size()-1;i>=0;i--){
		    	//先将待移动的身体块在map上的标记清空(除了新尾巴） 
				if(body[i].x!=-1&&body[i].y!=-1){
					game.map[body[i].x][body[i].y]=0;
				}
								
				//然后移动身体块(除了脑袋）
				if(i!=0){
				    body[i].x=body[i-1].x;
				    body[i].y=body[i-1].y;
				}
			}
			
			//再移动脑袋
			switch(direction){
				case 1:body[0].x--;break;
				case 2:body[0].y++;break;
				case 3:body[0].x++;break;
				case 4:body[0].y--;break;
			}
			
			//重新在map上标记整条蛇
			for(int i=0;i<body.size();i++){
				int sign=5;//蛇尾巴记号
				if(i==0){
					//蛇头要特殊标记
					sign=direction;
				}
				
				game.map[body[i].x][body[i].y]=sign; 
			}
			
			return;	
		} 
}; 